package com.kokotchy.tuxcontrol;

import java.util.HashMap;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

import com.kokotchy.tuxcontrol.provider.MessageList;
import com.kokotchy.tuxcontrol.provider.MessageList.Messages;

/**
 * Messages provider
 * 
 * $Date: 2009-12-30 15:09:35 +0000 (Wed, 30 Dec 2009) $
 * 
 * @author $Author: kokotchy $
 * @version $Revision: 18 $
 * 
 */
public class MessagesProvider extends ContentProvider {
	/**
	 * Helper to access database
	 * 
	 * @author $Author: kokotchy $
	 * 
	 */
	private static class DatabaseHelper extends SQLiteOpenHelper {

		/**
		 * Create a new database helper
		 * 
		 * @param context
		 *            Context
		 */
		DatabaseHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			db.execSQL(DATABASE_CREATE);
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
					+ newVersion + ", which will destroy all old data");
			db.execSQL("DROP TABLE IF EXISTS " + MESSAGES_TABLE_NAME);
			onCreate(db);
		}

	}

	/**
	 * TAG used when debugging
	 */
	private static final String TAG = "MessagesProvider";

	/**
	 * Name of the table with all messages
	 */
	private static final String MESSAGES_TABLE_NAME = "messages";

	/**
	 * Creation query
	 */
	private static final String DATABASE_CREATE = "CREATE TABLE "
			+ MESSAGES_TABLE_NAME + "(" + Messages._ID
			+ " INTEGER PRIMARY KEY AUTOINCREMENT, " + Messages.LOCUTOR
			+ " TEXT NOT NULL, " + Messages.MESSAGE + " TEXT NOT NULL, "
			+ Messages.DATE + " DATETIME DEFAULT CURRENT_TIMESTAMP);";

	/**
	 * Name of the database
	 */
	private static final String DATABASE_NAME = "messages.db";

	/**
	 * Version of the database
	 */
	private static final int DATABASE_VERSION = 2;

	/**
	 * Id for the type of a single message
	 */
	private static final int MESSAGE_ID = 2;

	/**
	 * Id for the type of a list of message
	 */
	private static final int MESSAGES = 1;

	/**
	 * Projection to use
	 */
	private static HashMap<String, String> sMessagesProjectionMap;

	/**
	 * Uri Matcher
	 */
	private static final UriMatcher sUriMatcher;

	static {
		sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		sUriMatcher.addURI(MessageList.AUTHORITY, "messages", MESSAGES);
		sUriMatcher.addURI(MessageList.AUTHORITY, "messages/#", MESSAGE_ID);

		sMessagesProjectionMap = new HashMap<String, String>();
		sMessagesProjectionMap.put(Messages._ID, Messages._ID);
		sMessagesProjectionMap.put(Messages.LOCUTOR, Messages.LOCUTOR);
		sMessagesProjectionMap.put(Messages.MESSAGE, Messages.MESSAGE);
		sMessagesProjectionMap.put(Messages.DATE, Messages.DATE);
	}

	/**
	 * Database helper
	 */
	private DatabaseHelper mOpenHelper;

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		int count;
		switch (sUriMatcher.match(uri)) {
		case MESSAGES:
			count = db.delete(MESSAGES_TABLE_NAME, selection, selectionArgs);
			break;

		case MESSAGE_ID:
			String messageId = uri.getPathSegments().get(1);
			count = db.delete(MESSAGES_TABLE_NAME, Messages._ID
					+ "="
					+ messageId
					+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
							+ ')' : ""), selectionArgs);
			break;

		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		getContext().getContentResolver().notifyChange(uri, null);
		return count;
	}

	@Override
	public String getType(Uri uri) {
		switch (sUriMatcher.match(uri)) {
		case MESSAGES:
			return Messages.CONTENT_TYPE;
		case MESSAGE_ID:
			return Messages.CONTENT_ITEM_TYPE;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
	}

	@Override
	public Uri insert(Uri uri, ContentValues initialValues) {
		// Validate the requested uri
		if (sUriMatcher.match(uri) != MESSAGES) {
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		ContentValues values;
		if (initialValues != null) {
			values = new ContentValues(initialValues);
		} else {
			values = new ContentValues();
		}

		if (values.containsKey(MessageList.Messages.LOCUTOR) == false) {
			values.put(MessageList.Messages.LOCUTOR, "Brian");
		}

		if (values.containsKey(MessageList.Messages.MESSAGE) == false) {
			values.put(MessageList.Messages.MESSAGE, "");
		}

		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		long rowId = db.insert(MESSAGES_TABLE_NAME, Messages.MESSAGE, values);
		if (rowId > 0) {
			Uri messageUri = ContentUris.withAppendedId(
					MessageList.Messages.CONTENT_URI, rowId);
			getContext().getContentResolver().notifyChange(messageUri, null);
			Log.v(TAG, "Message saved");
			return messageUri;
		}

		throw new SQLException("Failed to insert row into " + uri);
	}

	@Override
	public boolean onCreate() {
		mOpenHelper = new DatabaseHelper(getContext());
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		switch (sUriMatcher.match(uri)) {
		case MESSAGES:
			qb.setTables(MESSAGES_TABLE_NAME);
			qb.setProjectionMap(sMessagesProjectionMap);
			break;
		case MESSAGE_ID:
			qb.setTables(MESSAGES_TABLE_NAME);
			qb.setProjectionMap(sMessagesProjectionMap);
			qb.appendWhere(Messages._ID + "=" + uri.getPathSegments().get(1));
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		// If no sort order is specified use the default
		String orderBy;
		if (TextUtils.isEmpty(sortOrder)) {
			orderBy = MessageList.Messages.DEFAULT_SORT_ORDER;
		} else {
			orderBy = sortOrder;
		}

		// Get the database and run the query
		SQLiteDatabase db = mOpenHelper.getReadableDatabase();
		Cursor c = qb.query(db, projection, selection, selectionArgs, null,
				null, orderBy);

		// Tell the cursor what uri to watch, so it knows when its source data
		// changes
		c.setNotificationUri(getContext().getContentResolver(), uri);
		return c;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		int count;
		switch (sUriMatcher.match(uri)) {
		case MESSAGES:
			count = db.update(MESSAGES_TABLE_NAME, values, selection,
					selectionArgs);
			break;

		case MESSAGE_ID:
			String messageId = uri.getPathSegments().get(1);
			count = db.update(MESSAGES_TABLE_NAME, values, Messages._ID
					+ "="
					+ messageId
					+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
							+ ')' : ""), selectionArgs);
			break;

		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		getContext().getContentResolver().notifyChange(uri, null);
		return count;
	}

}
